﻿using System;
using System.Security.Cryptography;

namespace boda.utilities.Securities
{
    public class Registers
    {
        /// <summary>
        /// 1. 获取用户的hardwareCode
        /// 2. 由服务端生成licenseKey，提供给客户端
        /// 3. hardwareCode和licenseKey两者组合生成registrationKey
        /// 4. registrationKey注册码保存本地
        /// 将硬件码和注册码拼接成一个字符串，作为待加密的明文。
        /// 使用Rfc2898DeriveBytes类进行加密，这是一种基于密码学哈希函数的加密方式。
        /// 通过执行导出密钥操作可以计算出加盐哈希值，随后从结果中截取指定数量的字节以实现密钥的生成。
        /// 最后，将生成的字节数组转换成 Base64 编码字符串，并返回该字符串作为注册码。
        /// 当用户输入注册码时，程序会将其与硬件码匹配验证。
        /// </summary>
        /// <param name="hardwareCode"></param>
        /// <param name="licenseKey"></param>
        /// <returns></returns>
        public static string GenerateRegistrationKey(string hardwareCode, string licenseKey)
        {
            // 加盐，提高加密安全度
            byte[] salt = new byte[] { 0x1a, 0x32, 0xff, 0xa5, 0x21 };

            // 将硬件码和注册码拼接
            string plainText = string.Format("{0}:{1}", hardwareCode, licenseKey);

            using (Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(plainText, salt, 10000))
            {
                byte[] key = rfc.GetBytes(16); // 生成16字节长度的密钥
                return Convert.ToBase64String(key); // 将密钥转换成 Base64 编码字符串，并返回
            }
        }

        /// <summary>
        /// 首先将硬件码和注册码拼接成一个字符串作为明文，使用Rfc2898DeriveBytes类进行加密，得到加盐哈希值，随后从结果中截取指定数量的字节以实现密钥的生成。
        /// 比较验证过的注册码和用户输入的注册码是否相等，如果两者相等，则说明该注册码有效。
        /// 当用户输入正确的注册码时，我们可以将其保存在本地存储或数据库中，供以后的检查使用。
        /// 在每次程序启动时，程序可以检查本地存储或数据库是否存在有效的注册信息，如果存在则表示该软件已成功注册。
        /// </summary>
        /// <param name="hardwareCode"></param>
        /// <param name="licenseKey"></param>
        /// <param name="registrationKey"></param>
        /// <returns></returns>
        public static bool VerifyRegistrationKey(string hardwareCode, string licenseKey, string registrationKey)
        {
            // 加盐，提高加密安全度
            byte[] salt = new byte[] { 0x1a, 0x32, 0xff, 0xa5, 0x21 };

            // 将硬件码和注册码拼接
            string plainText = string.Format("{0}:{1}", hardwareCode, licenseKey);

            using (Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(plainText, salt, 10000))
            {
                byte[] key = rfc.GetBytes(16); // 生成16字节长度的密钥

                // 比较验证过的注册码和用户输入的注册码是否相等
                string verifiedRegistrationKey = Convert.ToBase64String(key);
                return verifiedRegistrationKey.Equals(registrationKey);
            }
        }
    }
}
